package com.jzt.jk.open.api.filter;

import com.jzt.jk.open.api.GlobalConstant;
import com.jzt.jk.open.api.exception.ForbiddenException;
import com.jzt.jk.open.api.service.OpenApiConfigCacheService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局认证请求
 * <p>
 * 作者：lizw <br/>
 * 创建时间：2021/01/26 11:36 <br/>
 */
@Component
@Slf4j
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    private static final int ORDER = Ordered.LOWEST_PRECEDENCE;

    @Autowired
    private OpenApiConfigCacheService openApiConfigCacheService;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        final String path = request.getPath().value();
        final String method = StringUtils.upperCase(request.getMethodValue());
        log.debug(" -> [{}] | {}", method, path);
        // 当前Route
        final Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        if (route == null || StringUtils.isBlank(route.getId())) {
            throw NotFoundException.create(true, "404 Not Found");
        }
        final String appKey = request.getHeaders().getFirst(GlobalConstant.App_Key_Header);
        final String appSecret = request.getHeaders().getFirst(GlobalConstant.App_Secret_Header);
        if (!openApiConfigCacheService.canAccess(appKey, appSecret, path, method)) {
            throw new ForbiddenException("403 Forbidden");
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return ORDER;
    }
}
